home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Java 1996 August
/
Java - Summer 1996.iso
/
kaffe-0.2
/
kaffe
/
classMethod.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-14
|
10KB
|
511 lines
/*
* classMethod.c
* Dictionary of classes, methods and fields.
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
*/
#define CDBG(s)
#define MDBG(s)
#define FDBG(s)
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "gtypes.h"
#include "constants.h"
#include "classMethod.h"
#include "code.h"
#include "access.h"
#include "readClass.h"
#include "baseClasses.h"
#include "errors.h"
extern strpair* initpair; /* Class init pair <clinit>()V */
extern strpair* finalpair; /* Class finalize pair finalize()V */
extern classes* classInitHead;
extern int classInitLevel;
static classes* classPool[CLASSHASHSZ];
methods* methodList; /* For exception processing */
static classes* internalAddClass(char*, char*, int, char*, classes*, int, constants*);
classes*
addClass(constIndex c, constIndex s, u2 flags, constants* pool)
{
char* str;
char* sstr;
classes* cl;
classes* su;
int basesize;
char sig[MAXSIG];
/* Find the name of the class */
if (pool->tags[c] != CONSTANT_Class) {
CDBG( printf("addClass: not a class.\n"); )
return (0);
}
c = pool->data[c];
if (pool->tags[c] != CONSTANT_Utf8) {
CDBG( printf("addClass: not a Utf8.\n"); )
return (0);
}
str = (uint8*)pool->data[c];
assert(strlen(str) > 0);
/* Build signature */
if (str[0] != '[') {
strcpy(sig, "L");
strcat(sig, str);
strcat(sig, ";");
}
else {
strcpy(sig, str);
}
/* Find the name of the super class */
if (s != 0) {
if (pool->tags[s] != CONSTANT_Class) {
CDBG( printf("addClass: not a class.\n"); )
return (0);
}
s = pool->data[s];
if (pool->tags[s] != CONSTANT_Utf8) {
CDBG( printf("addClass: not a Utf8.\n"); )
return (0);
}
sstr = (uint8*)pool->data[s];
/* Make sure it's loaded in */
su = lookupClass(sstr);
if (su == 0) {
return (0);
}
basesize = su->fsize;
}
else {
su = 0;
basesize = 0;
sstr = 0;
}
CDBG( printf("Adding class %s (%x)\n", str, flags); )
return (internalAddClass(str, addString(sig), flags, sstr, su, basesize, pool));
}
classes*
internalAddClass(char* str, char* sig, int flags, char* sstr, classes* su, int basesize, constants* pool)
{
classes** clp;
classes* cl;
methodTable* mt;
uint32 hash;
int i;
for (i = 0, hash = 0; str[i] != 0; i++) {
hash = hash * 33 + str[i];
}
hash %= CLASSHASHSZ;
clp = &classPool[hash];
#ifdef DEBUG
while (*clp != 0) {
assert(str != (*clp)->name);
clp = &(*clp)->next;
}
#endif
/* Allocate a class - it's an object too! */
cl = alloc_class();
if (cl == 0) {
return (0);
}
mt = (methodTable*)calloc(sizeof(methodTable), 1);
if (mt == 0) {
return (0);
}
mt->class = cl;
cl->name = str;
cl->sig = sig;
cl->supername = sstr;
cl->constants = pool;
cl->methodList = 0;
cl->fieldList = 0;
cl->staticFieldList = 0;
cl->superclass = su;
cl->fsize = basesize;
cl->sfsize = 0;
cl->accflags = flags;
cl->mtable = mt;
cl->staticFields = 0;
cl->interface = 0;
cl->interface_len = 0;
cl->state = CSTATE_OK;
cl->final = false;
/* Add into list */
cl->next = *clp;
*clp = cl;
return (cl);
}
methods*
addMethod(classes* c, method_info* m)
{
constIndex nc;
constIndex sc;
methods** mptr;
methods* mt;
constants* pool;
strpair* pair;
pool = c->constants;
nc = m->name_index;
if (pool->tags[nc] != CONSTANT_Utf8) {
MDBG( printf("addMethod: no method name.\n"); )
return (0);
}
sc = m->signature_index;
if (pool->tags[sc] != CONSTANT_Utf8) {
MDBG( printf("addMethod: no signature name.\n"); )
return (0);
}
pair = addStringConstantPair((char*)pool->data[nc], (char*)pool->data[sc]);
assert(pair != 0);
/* Mark class for init if this is the class init method */
if (pair == initpair) {
c->state = CSTATE_NEEDINIT;
}
else if (pair == finalpair) {
c->final = true;
}
/* Search down class for method name - don't allow duplicates */
mptr = &c->methodList;
#ifdef DEBUG
while (*mptr != 0) {
assert(pair != (*mptr)->pair);
mptr = &(*mptr)->next;
}
#endif
MDBG( printf("Adding method %s:%s%s (%x)\n", c->name, pool->data[nc], pool->data[sc], m->access_flags); )
mt = (methods*)malloc(sizeof(methods));
if (mt == 0) {
return (0);
}
mt->pair = pair;
mt->class = c;
mt->accflags = m->access_flags;
mt->code = 0;
mt->insn = 0;
mt->ncode = 0;
mt->constants = pool;
mt->stacksz = 0;
mt->localsz = 0;
mt->exception_table = 0;
mt->exception_table_len = 0;
mt->exception_next = 0;
mt->tableswitches = 0;
mt->lookupswitches = 0;
countInsAndOuts((char*)pool->data[sc], &mt->ins, &mt->outs);
mt->next = *mptr;
*mptr = mt;
return (mt);
}
fields*
addField(classes* c, field_info* f)
{
constIndex nc;
constIndex sc;
fields** fptr;
fields* ft;
char* sig;
constants* pool;
int* optr;
pool = c->constants;
nc = f->name_index;
if (pool->tags[nc] != CONSTANT_Utf8) {
FDBG( printf("addField: no field name.\n"); )
return (0);
}
/* Search down class for field name */
if (f->access_flags & ACC_STATIC) {
fptr = &c->staticFieldList;
optr = &c->sfsize;
}
else {
fptr = &c->fieldList;
optr = &c->fsize;
}
#ifdef DEBUG
while (*fptr != 0) {
assert((char*)pool->data[nc] != (*fptr)->name);
fptr = &(*fptr)->next;
}
#endif
FDBG( printf("Adding field %s:%s\n", c->name, pool->data[nc]); )
sc = f->signature_index;
if (pool->tags[sc] != CONSTANT_Utf8) {
FDBG( printf("addField: no signature name.\n"); )
return (0);
}
sig = (char*)pool->data[sc];
ft = (fields*)malloc(sizeof(fields));
if (ft == 0) {
return (0);
}
ft->name = (char*)pool->data[nc];
ft->sig = sig;
ft->class = c;
ft->accflags = f->access_flags;
ft->size = sizeofSig(&sig);
ft->offset = *optr;
(*optr) += ft->size;
ft->next = *fptr;
*fptr = ft;
return (ft);
}
void
addMethodCode(methods* m, Code* c)
{
m->code = c->code;
m->codelen = c->code_length;
m->stacksz = c->max_stack;
m->localsz = c->max_locals;
m->exception_table = c->exception_table;
m->exception_table_len = c->exception_table_length;
}
void
addInterfaces(classes* c, int inr, classes** inf)
{
assert(inr > 0);
c->interface = inf;
c->interface_len = inr;
}
/*
* Lookup a named class, loading it if necessary.
*/
classes*
lookupClass(char* c)
{
classes* class;
class = simpleLookupClass(c);
if (class == 0) {
/* Failed to find class, so must now load it */
findClass(c);
/* Once loaded, allocate the static data space */
class = simpleLookupClass(c);
assert(class != 0);
if (class->sfsize > 0) {
class->staticFields = (int*)calloc(class->sfsize, sizeof(int));
assert(class->staticFields != 0);
}
}
/* This class requires initialisation so place it at head of
current init list. If already at head of an init list (not this
one), then we have a recursive init which is an error */
if (class->state == CSTATE_OK || class->state == classInitLevel) {
/* Do nothing. */
}
else {
assert(class->state <= classInitLevel);
/* If already on a list, remove it */
if (class->state != CSTATE_NEEDINIT) {
if (class->prevInit == 0) {
throwException(ClassCircularityError);
}
class->prevInit->nextInit = class->nextInit;
if (class->nextInit != 0) {
class->nextInit->prevInit = class->prevInit;
}
}
/* Insert onto current list */
class->state = classInitLevel;
class->prevInit = 0;
class->nextInit = classInitHead;
if (classInitHead) {
classInitHead->prevInit = class;
}
classInitHead = class;
}
return (class);
}
classes*
simpleLookupClass(char* c)
{
uint32 hash;
char* str;
classes* clp;
for (str = c, hash = 0; *str != 0; str++) {
hash = hash * 33 + *str;
}
hash %= CLASSHASHSZ;
clp = classPool[hash];
while (clp != 0) {
if (c == clp->name) {
return (clp);
}
clp = clp->next;
}
return (0);
}
/*
* Lookup a named field.
*/
fields*
lookupClassField(char* c, char* f, bool isStatic)
{
classes* clp;
fields* fptr;
/* Look for class */
clp = lookupClass(c);
if (clp == 0) {
return (0);
}
/* Search down class for field name */
if (isStatic) {
fptr = clp->staticFieldList;
}
else {
fptr = clp->fieldList;
}
while (fptr != 0) {
if (f == fptr->name) {
return (fptr);
}
fptr = fptr->next;
}
FDBG( printf("Class:field lookup failed %s:%s\n", c, f); )
return (0);
}
/*
* Determine the number of arguments and return values from the
* method signature.
*/
void
countInsAndOuts(char* str, int* ins, int* outs)
{
*ins = sizeofSig(&str);
*outs = sizeofSig(&str);
}
/*
* Calculate size of data item based on signature.
*/
int
sizeofSig(char** strp)
{
int count;
char* str;
count = 0;
for (str = *strp; *str != 0; str++) {
switch (*str) {
case '(':
break;
case ')':
*strp = str+1;
return (count);
case 'I':
case 'Z':
case 'S':
case 'B':
case 'C':
case 'F':
count++;
break;
case 'D':
case 'J':
count += 2;
break;
case 'V':
break;
case '[':
count++;
str++;
if (*str == 'L') {
while (*str != ';') {
str++;
}
}
break;
case 'L':
count++;
/* Skip to end of reference */
while (*str != ';') {
str++;
}
break;
default:
abort();
}
}
*strp = str;
return (count);
}
/*
* Add this method to the method list so we can find it when
* handling exceptions.
*/
void
establishMethod(methods* m)
{
m->exception_next = methodList;
methodList = m;
}
/*
* Lookup an array class.
*/
classes*
lookupArray(char* c)
{
classes* class;
class = simpleLookupClass(c);
if (class == 0) {
class = internalAddClass(c, c, 0, 0, 0, 0, 0);
CDBG( if (class == 0) {
printf("Array Class %s not loaded.\n", c);
} )
}
return (class);
}